// PartGenerator.cpp: implementation of the PartGenerator class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PartGenerator.h"
#include "Part.h"
#include "Phsshare.h"
#include "DlgModelParam.h"
#include "ProjectManager.h"
#include "PipeGenerator.h"
#include <gevec3d.h>
#include <gepnt3d.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

PartGenerator& GetPartGenerator()
{
	ASSERT(GetProjectManager().CurProject());
	ASSERT(GetProjectManager().CurProject()->versionController());
	return GetProjectManager().CurProject()->versionController()->CurPartGenerator();
}
namespace VersionControl
{
	IMPLEMENT_SINGLETON(PartGenerator)
		
		PartGenerator::PartGenerator()
	{
		
	}
	
	PartGenerator::~PartGenerator()
	{
		
	}
	
	Part* PartGenerator::Generate(const CString &strCustomID, const CString& strStandardID)
	{	
		Part* pPart = NULL;
		pPart = new Part;
		ASSERT(project());
		pPart->project(project());
		pPart->SetCustomID(strCustomID);
		pPart->SetStandard(strStandardID);
		pPart->CreatePartFormer(pPart->GetID(), strStandardID);

		FunctionStack::Iterator* pIt = pPart->GetFunctionStack()->Get(FunctionObject::eINITFUNCTION);
		if(pIt != NULL)
		{
			for(pIt->Begin(); !pIt->End(); pIt->Next())
			{
				FunctionObject* pObject = pIt->Get();
				ASSERT(pObject);
				BOOL bResult = pObject->Execute();
				ASSERT(bResult);
			}
			delete pIt;
		}
//		GetCurDatabase().CopyData(*pPart, part);
		return pPart;
	}
	
	Part* PartGenerator::Generate()
	{
		CDlgModelParam dlg;
		if(dlg.DoModal() == IDOK)
		{
			return dlg.GetPart();
		}
		return NULL;
	}
	
	Part* PartGenerator::Generate(Part* pPart)
	{
		CDlgModelParam dlg(pPart);
		if(dlg.DoModal() == IDOK)
		{
			return dlg.GetPart();
		}
		return NULL;
	}
	
	Part* PartGenerator::Generate(DAWrapper::RecordsetPtrWrap& rs)
	{
		ASSERT(!rs.IsBOF() && !rs.IsEOF());

		CString strPartID = rs.GetString(_T("PF_ID"));
		ASSERT(!strPartID.IsEmpty());
		CString strStandard = rs.GetString(_T("Part_Standard_ID"));

		Part* pPart = NULL;
		if(strPartID == PipeGenerator::PipeID())
		{
			pPart = PipeGenerator::Instance()->Generate();			
		}
		else
		{
			pPart = Generate(strPartID, strStandard);
		}
		ASSERT(pPart);

		pPart->SetCustomID(strPartID);
		pPart->SetStandard(strStandard);
		pPart->PartIndex(rs.GetInt(_T("Part_ID")));
		pPart->ModelMatrix(GetPartMatrix(rs));
		if(rs.GetInt(_T("Attach")))
			pPart->SetAttach();

		GetPartProperty(pPart, rs);
		pPart->EffectProperty();
		pPart->SetRead();
		return pPart;
	}

	AcGeMatrix3d PartGenerator::GetPartMatrix(DAWrapper::RecordsetPtrWrap& rs)
	{
		AcGePoint3d Original;
		AcGeVector3d vX;
		AcGeVector3d vY;
		AcGeVector3d vZ;

		Original.x = rs.GetDouble(_T("Pos_X"));
		Original.y = rs.GetDouble(_T("Pos_Y"));
		Original.z = rs.GetDouble(_T("Pos_Z"));

		vX.x = rs.GetDouble(_T("Dir_X_X"));
		vX.y = rs.GetDouble(_T("Dir_X_Y"));
		vX.z = rs.GetDouble(_T("Dir_X_Z"));

		vZ.x = rs.GetDouble(_T("Dir_Z_X"));
		vZ.y = rs.GetDouble(_T("Dir_Z_Y"));
		vZ.z = rs.GetDouble(_T("Dir_Z_Z"));

		vY = vZ.crossProduct(vX);

		AcGeMatrix3d matrix;
		matrix.setCoordSystem(Original, vX, vY, vZ);

		return matrix;
	}

	void PartGenerator::GetPartProperty(Part* pPart, RecordsetPtrWrap& partrs)
	{
		ASSERT(pPart);
		
		CString strSql;
		strSql.Format(_T("Select * from Properties_Of_Part where \
						Part_ID = %d"), pPart->PartIndex());

		RecordsetPtrWrap rs;
		_ConnectionPtr pCon = partrs.GetSource();
		ASSERT(pCon != NULL);

		HRESULT hr = rs.Set(strSql, pCon);
		if(hr != S_OK)
		{
			ASSERT(FALSE);
			return;
		}

		CString strPropertyID;
		pPart->CloseGetPropertyTrigger();
		while(!rs.IsBOF() && !rs.IsEOF())
		{
			strPropertyID = rs.GetString(_T("Property_ID"));
			ASSERT(strPropertyID);

			pPart->SetVariableValue(strPropertyID, vtos(rs.GetCollect(_T("Property_Value"))));
			ASSERT(pPart->GetProperty(strPropertyID));
			rs.MoveNext();
		} 
		pPart->OpenGetPropertyTrigger();
		pPart->RunGetPropertyTrigger();
		
		rs.MoveFirst();
		pPart->CloseGetPropertyTrigger();
		while(!rs.IsBOF() && !rs.IsEOF())
		{
			strPropertyID = rs.GetString(_T("Property_ID"));
			ASSERT(strPropertyID);

			pPart->SetVariableValue(strPropertyID, vtos(rs.GetCollect(_T("Property_Value"))));
			ASSERT(pPart->GetProperty(strPropertyID));
			pPart->GetProperty(strPropertyID)->SetKnown();
			rs.MoveNext();
		} 
		pPart->OpenGetPropertyTrigger();
	}
}